﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using TencentCloud.Ame.V20190916.Models;
using TencentCloud.Privatedns.V20201028.Models;
using TencentCloud.Tcss.V20201101.Models;
using ZenSystemService.Api.Common;
using ZenSystemService.Api.Data;
using ZenSystemService.Api.Domain;
using ZenSystemService.Api.DTOs;
using ZenSystemService.Api.DTOs.Users;
using ZenSystemService.Api.Entities;
using System.Runtime.CompilerServices;
using TencentCloud.Vpc.V20170312.Models;
using ZenSystemService.Api.DTOs.Legency;
using ZenSystemService.Api.Common.Encryption;
using Microsoft.IdentityModel.Tokens;
namespace ZenSystemService.Api.Services
{
    public class UserService
    {
        private readonly ApplicationDbContext _context;
        private readonly IMapper _mapper;
        private const string CoachDefaultPassword = "123456";
        private readonly IConfiguration _configuration;
        private readonly IEncryptionService _encryptionService;
        private readonly TraineeOrderService _traineeOrderService;
        public UserService(ApplicationDbContext context, IMapper mapper, IConfiguration configuration, IEncryptionService encryptionService, TraineeOrderService traineeOrderService)
        {
            _context = context;
            _mapper = mapper;
            _configuration = configuration;
            _encryptionService = encryptionService;
            _traineeOrderService = traineeOrderService;
        }

        public async Task<User> GetUserByIdAsync(int id)
        {
            try
            {
                return await _context.Users
                    .Include(u => u.UserRoles)
                    .ThenInclude(ur => ur.Role)
                    .FirstAsync(u => u.UserId == id);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public User GetUserById(int id)
        {
            try
            {
                return  _context.Users
                    .Include(u => u.UserRoles)
                    .ThenInclude(ur => ur.Role)
                    .First(u => u.UserId == id);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public IEnumerable<UserDTO> GetUsersByRoleAsync(GetUserByRoleCriteriaDTO criteria)
        {
            var users = _context.Users.Include(u => u.Institution)
                .Include(u => u.UserRoles).ThenInclude(ur => ur.Role)
                .Include(u => u.Coach)
                .Where(u => 
                    (criteria.InstitutionId == null || 
                        (u.Institution != null 
                            && u.Institution.InstitutionId == criteria.InstitutionId
                        )
                    )
                    && (string.IsNullOrEmpty(criteria.RoleName) 
                        || u.UserRoles.Any(ur => ur.Role.Name == criteria.RoleName))
                    && (string.IsNullOrEmpty(criteria.UserType) 
                        || u.UserType == criteria.UserType));
            var userList = users.ToList();
            return _mapper.Map<IEnumerable<UserDTO>>(userList);
        }

     


        public IEnumerable<User> GetTraineeList(int page, int pageSize, int? InstitutionId, int? Coachid, int SearchType,string searchKey,out int recordCount)
        {
            var list = _context.Users.Where(u => u.Enabled == "1" && u.UserType == ((int)UserType.Trainee).ToString());

            if (SearchType != 0)
            {
                if (list != null && SearchType == 1)//主账号
                {
                    list = list.Where(item => !item.ParentUserId.HasValue || item.ParentUserId.Value == 0);
                }
                if (list != null && SearchType == 2)//子账号
                {
                    list = list.Where(item => item.ParentUserId.HasValue && item.ParentUserId.Value > 0);
                }
            }

            if (list != null && InstitutionId.HasValue && InstitutionId.Value > 0)
            {
                list = list.Where(item => item.InstitutionId == InstitutionId);
            }

            if (list != null && Coachid.HasValue && Coachid.Value > 0)
            {
                List<TraineeCourseSurplus> TraineeCourseSurplusList = _traineeOrderService.GetTraineeCourseSurplusByCoachId(Coachid.Value);
                if (TraineeCourseSurplusList == null || TraineeCourseSurplusList.Count == 0)
                {
                    list = list.Where(item => item.CoachId == Coachid.Value);
                }
                else
                {
                    int[] TraineeIdArr = new int[TraineeCourseSurplusList.Count];
                    for (int i = 0; i < TraineeCourseSurplusList.Count; i++)
                    {
                        TraineeIdArr[i] = TraineeCourseSurplusList[i].TraineeId;
                    }
                    list = list.Where(item => TraineeIdArr.Contains(item.UserId) || item.CoachId == Coachid.Value);
                }
            }
            if (list != null && !searchKey.IsNullOrEmpty())
            {
                list = list.Where(item => item.RealName.Contains(searchKey) || item.Mobile.Contains(searchKey));
            }

            recordCount = list == null ? 0 : list.Count();
            if (page == 0 || pageSize == 0)
            {
                return list;
            }
            else
            {
                list = list.Skip((page - 1) * pageSize).Take(pageSize);
            }
            return list;
        }



        public IEnumerable<User> GetTraineeList(int page, int pageSize, int? InstitutionId, int? CourseTypeId, int? Coachid, out int recordCount)
        {
            var list = _context.Users.Where(u => u.Enabled == "1" && u.UserType == ((int)UserType.Trainee).ToString());
            if (list != null && InstitutionId.HasValue && InstitutionId.Value > 0)
            {
                list = list.Where(item => item.InstitutionId == InstitutionId);
            }
            if (list != null && CourseTypeId.HasValue && CourseTypeId.Value > 0)
            {
                List<TraineeCourseSurplus> TraineeCourseSurplusList = _traineeOrderService.GetTraineeCourseSurplusByCourseTypeId(CourseTypeId.Value);
                if (TraineeCourseSurplusList == null || TraineeCourseSurplusList.Count == 0)
                {
                    recordCount = 0;
                    return null;
                }
                TraineeCourseSurplusList = TraineeCourseSurplusList.Where(item => item.SurplusCourseNum > 0).ToList();
                if (TraineeCourseSurplusList == null || TraineeCourseSurplusList.Count == 0)
                {
                    recordCount = 0;
                    return null;
                }
                int[] TraineeIdArr = new int[TraineeCourseSurplusList.Count];
                for (int i = 0; i < TraineeCourseSurplusList.Count; i++)
                {
                    TraineeIdArr[i] = TraineeCourseSurplusList[i].TraineeId;
                }
                list = list.Where(item => TraineeIdArr.Contains(item.UserId));
            }
            if (list != null && Coachid.HasValue && Coachid.Value > 0)
            {
                List<TraineeCourseSurplus> TraineeCourseSurplusList = _traineeOrderService.GetTraineeCourseSurplusByCoachId(Coachid.Value);
                if (TraineeCourseSurplusList == null || TraineeCourseSurplusList.Count == 0)
                {
                    list = list.Where(item => item.CoachId == Coachid.Value);
                }
                TraineeCourseSurplusList = TraineeCourseSurplusList.Where(item => item.SurplusCourseNum > 0).ToList();
                if (TraineeCourseSurplusList == null || TraineeCourseSurplusList.Count == 0)
                {
                    list = list.Where(item => item.CoachId == Coachid.Value);
                }
                int[] TraineeIdArr = new int[TraineeCourseSurplusList.Count];
                for (int i = 0; i < TraineeCourseSurplusList.Count; i++)
                {
                    TraineeIdArr[i] = TraineeCourseSurplusList[i].TraineeId;
                }
                list = list.Where(item => TraineeIdArr.Contains(item.UserId));
            }

            recordCount = list == null ? 0 : list.Count();
            if (page == 0 || pageSize == 0)
            {
                return list;
            }
            else
            {
                list = list.Skip((page - 1) * pageSize).Take(pageSize);
            }
            return list;
        }

        public async Task<User> GetUserByUsernameAsync(string username)
        {
            return await _context.Users.SingleOrDefaultAsync(u => u.Username == username && u.Enabled == "1");
        }

        public async Task<bool> ValidateMobileIsExist(string mobile)
        {
            bool exists =await _context.Users.AnyAsync(u => u.Mobile == mobile && u.Enabled == "1");
            return exists;
        }
        /*
        public async Task<User> GetUserByPhoneAsync(string mobile)
        {
            return await _context.Users.SingleOrDefaultAsync(u => u.Mobile == mobile && u.Enabled == "1");
        }
        */
        public async Task<User> GetInstitutionUserByPhoneAsync(string mobile)
        {
            return await _context.Users.SingleOrDefaultAsync(u => u.Mobile == mobile && u.Enabled == "1"&&u.UserType==((int)UserType.Institution).ToString());
        }

        /// <summary>
        /// 根据手机号得到主账号学员
        /// </summary>
        /// <param name="mobile"></param>
        /// <returns></returns>
        public async Task<User> GetTraineeByPhoneAsync(string mobile)
        {
            try
            {
                return await _context.Users.SingleOrDefaultAsync(u => u.Mobile == mobile && u.Enabled == "1" && u.UserType == ((int)UserType.Trainee).ToString() && (!u.ParentUserId.HasValue || u.ParentUserId == 0));
            }
            catch(Exception ex)
            {
                return null;
            }
        }

        /*
        /// <summary>
        /// 根据手机号得到主子账号学员
        /// </summary>
        /// <param name="mobile"></param>
        /// <returns></returns>
        public async Task<User> GetMasterSonTraineeByPhoneAsync(string mobile)
        {
            try
            {
                return await _context.Users.SingleOrDefaultAsync(u => u.Mobile == mobile && u.Enabled == "1" && u.UserType == ((int)UserType.Trainee).ToString() && (!u.ParentUserId.HasValue || u.ParentUserId == 0));
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        */

        /// <summary>
        /// 获取子账号信息
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        public async Task<List<User>> GetTraineeSubAccountList(int userid)
        {
            return await _context.Users.Where(u => u.ParentUserId == userid && u.Enabled == "1" && u.UserType == ((int)UserType.Trainee).ToString()).ToListAsync();
        }


        public async Task<IEnumerable<User>> GetAllUsersAsync()
        {
            return await _context.Users.Where(item=>item.Enabled=="1").ToListAsync();
        }
        public bool CreateUser(ref User user)
        {
            _context.Users.Add(user);
            int count = _context.SaveChanges();
            return count > 0 ? true : false;
        }

        public async Task<bool> CreateUserAsync(User user)
        {
            _context.Users.Add(user);
            int count = _context.SaveChanges();
            return count > 0 ? true : false;
        }

        public bool CreateUserAsync(ref User user, string password)
        {
            user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(password);
            user.EncryptedPassword = _encryptionService.Encrypt(password);
            _context.Users.Add(user);
            int count = _context.SaveChanges();
            return count > 0 ? true : false;
        }

        public async Task<UserDTO> CreateUserAsync(UserDTO userDTO, string password)
        {
            var user = _mapper.Map<User>(userDTO);
            user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(password);
            user.EncryptedPassword = _encryptionService.Encrypt(password);
            _context.Users.Add(user);
            _context.SaveChanges();
            return _mapper.Map<UserDTO>(user);
        }

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="currentUser"></param>
        /// <param name="userDTO"></param>
        /// <returns></returns>
        public async Task<UserCreateResultDTO> CreateUserAsync(UserModel currentUser, UserCreateDTO userDTO)
        {
            var existedUser = _context.Users.FirstOrDefault(u => u.Mobile == userDTO.Mobile);
            if(existedUser != null)
            {
                return _mapper.Map<UserCreateResultDTO>(existedUser);
            }
            var user = _mapper.Map<User>(userDTO);
            var password = string.IsNullOrEmpty(userDTO.Password) ? CoachDefaultPassword : userDTO.Password;
            user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(password);
            user.EncryptedPassword = _encryptionService.Encrypt(password);
            user.InstitutionId = userDTO?.InstitutionId;
            _context.Users.Add(user);
            _context.SaveChanges();

            if (userDTO.UserType == ((int)UserType.Institution).ToString())
            {
                var userRole = await _context.Roles.FirstAsync(r => r.Name.Equals(userDTO.RoleName));
                _context.UserRoles.Add(new UserRole { UserId = user.UserId, RoleId = userRole.Id });
                _context.SaveChanges();
            }
            return _mapper.Map<UserCreateResultDTO>(user);
        }

        /// <summary>
        /// Legency user专用，和新系统用户的区别
        /// 1. InstitutionId取自配置文件
        /// 2. 新系统用Mobile作为唯一标识，Legency用username
        /// </summary>
        /// <param name="userDTO"></param>
        /// <returns></returns>
        public async Task<UserCreateResultDTO> CreateForLegencyUserAsync(LegencyUserCreateDTO userDTO)
        {
            if (userDTO == null)
                throw new Exception("用户信息不完整");
            var defaultInstitutionId = _configuration.GetValue<int>("InstitutionIdForLegencyUser");
            var existedUser = _context.Users.FirstOrDefault(u => u.Username == userDTO.Username);
            if (existedUser != null)
            {
                return _mapper.Map<UserCreateResultDTO>(existedUser);
            }
            var user = _mapper.Map<User>(userDTO);
            var password = string.IsNullOrEmpty(userDTO.Password) ? CoachDefaultPassword : userDTO.Password;
            user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(password);
            user.EncryptedPassword = _encryptionService.Encrypt(password);
            user.InstitutionId = defaultInstitutionId;//和新系统不同的地方
            user.UserType = ((int)UserType.Trainee).ToString();//和新系统不同的地方
            user.Enabled = "1";//和新系统不同的地方
            user.CreatedDate = DateTime.Now;//和新系统不同的地方
            _context.Users.Add(user);
            _context.SaveChanges();

            if (userDTO.UserType == ((int)UserType.Institution).ToString())
            {
                var userRole = await _context.Roles.FirstAsync(r => r.Name.Equals(userDTO.RoleName));
                _context.UserRoles.Add(new UserRole { UserId = user.UserId, RoleId = userRole.Id });
                _context.SaveChanges();
            }

            await _context.LegencyUserZenUsers.AddAsync(new LegencyUserZenUser
            {
                LegencyUserId = userDTO.LegencyUserId,
                ZenUserId = user.UserId
            });
            await _context.SaveChangesAsync();

            return _mapper.Map<UserCreateResultDTO>(user);
        }

        public async Task<bool> UpdateUserAsync(User user)
        {
            _context.Entry(user).State = EntityState.Modified;
            int count = await _context.SaveChangesAsync();
            return count > 0 ? true : false;
        }

        public async Task<UserCreateResultDTO> UpdateUserAsync(UserUpdateRequestDTO user)
        {
            var existedUser = _context.Users.FirstOrDefault(u => u.UserId == user.UserId);
            if (existedUser == null)
                return null;
            existedUser.UpdateFrom<User>(user);
            _context.Entry(existedUser).State = EntityState.Modified;
            await _context.SaveChangesAsync();
            return _mapper.Map<UserCreateResultDTO>(existedUser);
        }

        public async Task<bool> DeleteUserAsync(int id)
        {
            var user = await _context.Users.FindAsync(id);
            if (user != null)
            {
                _context.Users.Remove(user);
                int count =  await _context.SaveChangesAsync();
                return count > 0 ? true : false;
            }
            else
            {
                return false;
            }
        }


        /// <summary>
        /// 创建学员人物关系信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public async Task<bool> CreateTraineeCharacterRelationAsync(TraineeCharacterRelation _traineeCharacterRelation)
        {
            _context.TraineeCharacterRelations.Add(_traineeCharacterRelation);
            int count = await _context.SaveChangesAsync();
            return count > 0 ? true : false;
        }


        public async Task<TraineeCharacterRelation> GetTraineeCharacterRelationInfo(int ParentAccountUserId, int SubAccountUserId)
        {
            var _traineeCharacterRelation = _context.TraineeCharacterRelations.FirstOrDefault(u => u.ParentAccountUserId == ParentAccountUserId&&u.SubAccountUserId== SubAccountUserId);
            return _traineeCharacterRelation;
        }

        public async Task<bool> UpdateTraineeCharacterRelationAsync(TraineeCharacterRelation _traineeCharacterRelation)
        {
            _context.Entry(_traineeCharacterRelation).State = EntityState.Modified;
            int count = await _context.SaveChangesAsync();
            return count > 0 ? true : false;
        }


        /// <summary>
        /// 创建zen系统与legency系统人员关联信息
        /// </summary>
        /// <param name="_legencyUserZenUser"></param>
        /// <returns></returns>
        public async Task<bool> CreateLegencyUserZenUser(LegencyUserZenUser _legencyUserZenUser)
        {
            _context.LegencyUserZenUsers.Add(_legencyUserZenUser);
            int count = await _context.SaveChangesAsync();
            return count > 0 ? true : false;
        }


        public async Task<LegencyUserZenUser> GetLegencyUserZenUserInfo(int userid)
        {
            var _legencyUserZenUser = _context.LegencyUserZenUsers.FirstOrDefault(u => u.ZenUserId == userid);
            if (_legencyUserZenUser == null)
                return null;
            return _legencyUserZenUser;
        }

        
        public async Task<bool> AddZenBrightTestOrder(ZenBrightTestOrder _zenBrightTestOrder)
        {
            _context.ZenBrightTestOrders.Add(_zenBrightTestOrder);
            int count = await _context.SaveChangesAsync();
            return count > 0 ? true : false;
        }
        
    }
}